package br.com.loja.view.swing;

import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import br.com.loja.model.service.exception.ServiceException;
import br.com.loja.model.service.factory.ServiceFactory;
import br.com.loja.mvp.presenter.DefaultEditorPresenter;
import br.com.loja.mvp.model.BusinessPresenter;
import br.com.loja.mvp.presenter.Presenter;
import br.com.loja.util.i18n.Language;
import br.com.loja.view.swing.model.DefaultToolBarEditor;
import br.com.loja.view.swing.model.EntityDefaultTableModel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @brief Classe DefaultEntityView
 * @author David Luiz
 * @date 24/11/2014
 */
public class DefaultEntityEditor<T> extends JInternalFrame implements BusinessPresenter<T>, ActionListener {

    protected T model;
    protected final Presenter<T> presenter;
    protected EntityDefaultTableModel<T> tableModel;
    protected final Language language;
    private DefaultToolBarEditor toolbar;
    private JTable tableEntities;
    private JScrollPane scrollPane;
    private final JPanel formEntity;

    public DefaultEntityEditor(String title, Class<T> clazz) throws ServiceException {
        super();
        presenter = new DefaultEditorPresenter<>(clazz);
        formEntity = (JPanel) new PanelEntityEditor(clazz);
        language = Language.getInstance();
        setTitle(language.getString(title));
        init();

    }

    protected void clear() {
        if (isFormEntity()) {
            ((IFormEntity) formEntity).clearForm();
        }
    }

    protected void disableEdition(boolean op) {
        toolbar.getBtGravar().setEnabled(op);
        toolbar.getBtCancelar().setEnabled(op);
        toolbar.getBtNovo().setEnabled(!op);
        toolbar.getBtAlterar().setEnabled(false);
        toolbar.getBtRemover().setEnabled(false);
        tableEntities.setEnabled(!op);
        tableEntities.clearSelection();

        if (isFormEntity()) {
            ((IFormEntity) formEntity).disableForm(op);
            ((IFormEntity) formEntity).grabFocus();
        }

    }

    protected void disableEdition() {
        disableEdition(false);

    }

    protected void enableEdition() {
        disableEdition(true);
    }

    protected void executeSelectRow() {
        this.toolbar.getBtAlterar().setEnabled(true);
        this.toolbar.getBtRemover().setEnabled(true);
    }

    private void init() throws ServiceException {

        this.presenter.setView(this);

        tableEntities = new JTable();
        scrollPane = new JScrollPane();
        toolbar = new DefaultToolBarEditor(this);

        setBorder(null);
        setClosable(true);
        setIconifiable(true);
        setMaximizable(true);

        tableEntities.getSelectionModel().
                addListSelectionListener(new ListSelectionListener() {

                    @Override
                    public void valueChanged(ListSelectionEvent e) {
                        executeUpdateModel();
                    }

                });

        this.tableModel = new EntityDefaultTableModel(presenter.getClassModel());
        this.tableModel.setEntities(ServiceFactory.getServiceFactory().getService(presenter.getClassModel()).list());
        this.tableEntities.setModel(tableModel);

        scrollPane.setViewportView(tableEntities);

        //initComponents
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(scrollPane)
                                .addGroup(layout.createSequentialGroup()
                                        .addComponent(formEntity, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addGap(0, 0, Short.MAX_VALUE)))
                        .addContainerGap())
                .addComponent(toolbar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addComponent(toolbar, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(formEntity, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 231, Short.MAX_VALUE)
                        .addContainerGap())
        );

        pack();
    }

    private void executeUpdateModel() {
        if (tableEntities.isEnabled()) {
            int selectedRow = tableEntities.getSelectedRow();
            T modelSelected = null;

            if (isValidSelectedRow(selectedRow)) {
                modelSelected = (T) tableModel.getEntities().get(selectedRow);
                executeSelectRow();
            }

            if (model != null) {
                setModel(modelSelected);
                return;
            }

            if (isDifferentFromModel(modelSelected)) {
                setModel(modelSelected);
            }
        }
    }

    private boolean isDifferentFromModel(T modelSelected) {
        return !modelSelected.equals(model);
    }

    private boolean isValidSelectedRow(int selectedRow) {
        return selectedRow > -1;
    }

    private EntityDefaultTableModel getTableModel() throws ServiceException {

        EntityDefaultTableModel<T> defaultTableModel;

        if (tableModel == null) {
            defaultTableModel = new EntityDefaultTableModel(presenter.getClassModel());

        } else {
            defaultTableModel = this.tableModel;
            defaultTableModel.getEntities().clear();
        }

        defaultTableModel.setEntities(ServiceFactory.getServiceFactory().getService(presenter.getClassModel()).list());
        return defaultTableModel;
    }

    private void updateTable() throws ServiceException {
        clear();
        tableModel = getTableModel();
        tableEntities.setModel(tableModel);
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                tableEntities.updateUI();
            }
        });

    }

    @Override
    public void newEntity() {
        clear();
        enableEdition();
    }

    @Override
    public void editEntity() {
        enableEdition();
    }

    @Override
    public void removeEntity() {
        executeUpdateForm();
    }

    @Override
    public void saveEntity() {
        executeUpdateForm();
    }

    private void executeUpdateForm() {
        try {
            disableEdition();
            updateTable();
        } catch (ServiceException ex) {
            //implementar log
            System.err.println(ex.getMessage());
            ex.printStackTrace();
        }
    }

    @Override
    public void cancel() {
        setModel(presenter.getModel());
        disableEdition();
    }

    @Override
    public void setModel(T model) {
        this.model = model;
        presenter.setModel(model);
        if (model != null) {
            if (isFormEntity()) {
                ((IFormEntity) formEntity).setModel(model);
            }
        }
    }

    @Override
    public T getModel() {
        if (isFormEntity()) {
            model = (T) ((IFormEntity) formEntity).getModel(model);
        }

        return model;
    }

    private boolean isFormEntity() {
        return formEntity instanceof IFormEntity;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        String actionCommand = e.getActionCommand();

        switch (actionCommand) {

            case "novo":
                presenter.newEntity();
                break;

            case "alterar":
                presenter.editEntity();
                break;

            case "remover":
                presenter.removeEntity();
                break;

            case "gravar":
                presenter.saveEntity();
                break;

            case "cancelar":
                presenter.cancel();
                break;
        }

    }

}
